package com.bajiao.app.controller.user;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPObject;
import com.bajiao.app.base.AppBaseController;
import com.bajiao.common.api.vo.RestResult;
import com.bajiao.common.constant.CommonConstant;
import com.bajiao.common.constant._Whole;
import com.bajiao.common.exception.DataHandleException;
import com.bajiao.common.menu.ResultEnum;
import com.bajiao.common.util.AuthUtil;
import com.bajiao.common.util.PasswordUtil;
import com.bajiao.common.util.RedisUtil;
import com.bajiao.common.util.vans.VansTool;
import com.bajiao.dto.wx.WXBindDto;
import com.bajiao.dto.wx.WXLoginDto;
import com.bajiao.entity.store.Store;
import com.bajiao.entity.store.StoreUser;
import com.bajiao.entity.user.User;
import com.bajiao.service.config.ConfigService;
import com.bajiao.service.store.StoreService;
import com.bajiao.service.store.StoreUserService;
import com.bajiao.service.user.UserService;
import com.bajiao.third.utils.AliSmsUtils;
import com.bajiao.vo.store.StoreUserDetails;
import com.bajiao.vo.store.StoreUserInfo;
import com.bajiao.vo.user.UserDetails;
import com.bajiao.vo.user.UserInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.C;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Api(tags = "登录管理")
@RestController
@RequestMapping("/api/v1/login")
public class RestLoginController extends AppBaseController {

    @Resource
    private UserService userService;
    @Resource
    private ConfigService configService;
    @Autowired
    private RedisUtil redisUtil;

    @PostMapping(value = "/wx/auth")
    @ApiOperation(value = "微信小程序授权登录")
    public RestResult<UserDetails> wxAuthLogin(WXLoginDto dto) {
        //@create by FanJq 2024/7/8 15:21 解密encryptedData,获取用户信息
        JSONObject wxResult = getWxJsCode(dto);
        String openId = wxResult.getString("openId");
        User user = userService.getByOpenId(openId);
        //@create by FanJq 2024/7/8 15:23 未发现绑定信息返回特定code让前端跳转绑定手机号页面
        if (ObjectUtil.isNull(user))
            return fail(ResultEnum.NO_BIND);
        if (wxResult.containsKey("unionId") && StrUtil.isBlank(user.getUnionId())) {
            user.setUnionId(wxResult.getString("unionId"));
            userService.updateById(user);
        }

        UserDetails userDetails = createUserTokenMap(tokenBuild(user, 4, openId), user);
        if(redisUtil.get("newUser:" + openId) != null) {
            userDetails.setIsNewUser(1);
            redisUtil.del("newUser:" + openId);
        }else{
            userDetails.setIsNewUser(0);
        }
        return success(createUserTokenMap(tokenBuild(user, 4, openId), user));
    }

    @PostMapping(value = "/wx/bind")
    @ApiOperation(value = "微信小程序授权绑定")
    public RestResult<UserDetails> wxBind(WXBindDto dto) {
        try {
            //@create by FanJq 2024/7/8 15:21 解密encryptedData,获取用户信息
            JSONObject wxResult = getWxJsCode(dto);
            if (StrUtil.isBlank(wxResult.getString("phoneNumber")))
                throw new DataHandleException("未获取到手机号");
            //@create by FanJq 2024/7/8 15:27 满足openId下发条件的情况下，返回
            String openId = wxResult.getString("openid");// 用户唯一标识
            String unionId = wxResult.getString("unionid");// 用户唯一标识
            String mobile = wxResult.getString("phoneNumber");
            //查询用户是否存在
            User user = userService.queryByMobileAndNotDelFlag(mobile);
            //新用户
            if (ObjectUtil.isNull(user)) {
                //注册用户
                user = userService.wxRegister(mobile, openId, unionId, dto.getNickName(), dto.getAvatarUrl(), dto.getGender(), dto.getInviteCode());
                // 设置新用户标识
                redisUtil.set("newUser:" + openId, openId);
            }
            if (StrUtil.isBlank(user.getOpenId()) || !user.getOpenId().equals(openId)) {
                user.setOpenId(openId);
                if (wxResult.containsKey("unionId") && StrUtil.isBlank(user.getUnionId())) {
                    user.setUnionId(wxResult.getString("unionId"));
                }
                userService.updateById(user);
            }
            return success(createUserTokenMap(tokenBuild(user, 4, openId), user));
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return fail(ResultEnum.OPERATION_FAIL.getDesc());
    }

    @PostMapping(value = "/app/wx/auth")
    @ApiOperation(value = "App微信授权登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "code", value = "微信code", dataType = "String", required = true),
            @ApiImplicitParam(name = "source", value = "ios android", dataType = "String", required = true)
    })
    public RestResult<UserDetails> appAuthLogin(@RequestParam String code,
                                                @RequestParam String source) {
        Integer client = source.equals("android") ? _Whole.ONE : source.equals("ios") ? _Whole.TWO : _Whole.ZERO;
        if (client <= _Whole.ZERO)
            throw new DataHandleException("客户端异常，请检查参数");
        //@create by FanJq 2024/12/25 17:05 获取用户信息
        JSONObject wxResult = getWxAppCode(code);
        String openId = wxResult.getString("openid");
        User user = userService.getByOpenId(openId);
        //@create by FanJq 2024/7/8 15:23 未发现绑定信息返回特定code让前端跳转绑定手机号页面
        if (ObjectUtil.isNull(user))
            return fail(ResultEnum.NO_BIND);
        if (wxResult.containsKey("unionid") && StrUtil.isBlank(user.getUnionId())) {
            user.setUnionId(wxResult.getString("unionid"));
            userService.updateById(user);
        }
        return success(createUserTokenMap(tokenBuild(user, client, openId), user));
    }

    @PostMapping(value = "/captcha")
    @ApiOperation(value = "验证码登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "mobile", value = "手机号", dataType = "String", required = true),
            @ApiImplicitParam(name = "captcha", value = "验证码", dataType = "String", required = true),
            @ApiImplicitParam(name = "source", value = "ios android", dataType = "String", required = true)
    })
    public RestResult<UserDetails> captchaLogin(@RequestParam String mobile,
                                                @RequestParam String captcha,
                                                @RequestParam String source) {
        Integer client = source.equals("android") ? _Whole.ONE : source.equals("ios") ? _Whole.TWO : _Whole.ZERO;
        if (client <= _Whole.ZERO)
            throw new DataHandleException("客户端异常，请检查参数");
        //@create by FanJq 2024/12/25 17:18 校验验证码
        AliSmsUtils.check(mobile, CommonConstant.SMS_EVENT_LOGIN, captcha);
        //@create by FanJq 2024/12/25 17:05 获取用户信息
        User user = userService.queryByMobileAndNotDelFlag(mobile);
        //@create by FanJq 2024/7/8 15:23 未发现绑定信息返回特定code让前端跳转注册页面
        if (ObjectUtil.isNull(user))
            return fail(ResultEnum.NO_BIND);

        return success(createUserTokenMap(tokenBuild(user, client, ""), user));
    }

    @PostMapping(value = "/cipher")
    @ApiOperation(value = "密码登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "mobile", value = "手机号", dataType = "String", required = true),
            @ApiImplicitParam(name = "cipher", value = "密码", dataType = "String", required = true),
            @ApiImplicitParam(name = "source", value = "ios android", dataType = "String", required = true)
    })
    public RestResult<UserDetails> cipherLogin(@RequestParam String mobile,
                                                @RequestParam String cipher,
                                                @RequestParam String source) {
        Integer client = source.equals("android") ? _Whole.ONE : source.equals("ios") ? _Whole.TWO : _Whole.ZERO;
        if (client <= _Whole.ZERO)
            throw new DataHandleException("客户端异常，请检查参数");
        //@create by FanJq 2024/12/25 17:05 获取用户信息
        User user = userService.queryByMobileAndNotDelFlag(mobile);
        //@create by FanJq 2024/7/8 15:23 未发现绑定信息返回特定code让前端跳转注册页面
        if (ObjectUtil.isNull(user))
            return fail(ResultEnum.NO_BIND);
        String cipherText = PasswordUtil.encrypt(cipher, "", user.getSalt());
        if (!StrUtil.equals(user.getPassword(), cipherText))
            throw new DataHandleException("密码错误");

        return success(createUserTokenMap(tokenBuild(user, client, ""), user));
    }

    @PostMapping(value = "/secretFree/login")
    @ApiOperation(value = "免密登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "mobile", value = "手机号", dataType = "String", required = true),
            @ApiImplicitParam(name = "source", value = "ios android", dataType = "String", required = true)
    })
    public RestResult<UserDetails> secretFreeLogin(@RequestParam String mobile,
                                                   @RequestParam String source) {
        Integer client = source.equals("android") ? _Whole.ONE : source.equals("ios") ? _Whole.TWO : _Whole.ZERO;
        if (client <= _Whole.ZERO)
            throw new DataHandleException("客户端异常，请检查参数");
        //@create by FanJq 2024/12/25 17:05 获取用户信息
        User user = userService.queryByMobileAndNotDelFlag(mobile);
        //@create by FanJq 2024/7/8 15:23 未发现绑定信息返回特定code让前端跳转注册页面
        if (ObjectUtil.isNull(user))
            return fail(ResultEnum.NO_BIND);

        return success(createUserTokenMap(tokenBuild(user, client, ""), user));
    }

    @PostMapping(value = "/register")
    @ApiOperation(value = "App注册")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "mobile", value = "手机号", dataType = "String", required = true),
            @ApiImplicitParam(name = "captcha", value = "验证码", dataType = "String", required = true),
            @ApiImplicitParam(name = "cipher", value = "密码", dataType = "String", required = true),
            @ApiImplicitParam(name = "inviteCode", value = "邀请码", dataType = "String", required = true),
            @ApiImplicitParam(name = "source", value = "ios android", dataType = "String", required = true)
    })
    public RestResult<UserDetails> appRegister(@RequestParam String mobile,
                                               @RequestParam String captcha,
                                               @RequestParam String cipher,
                                               @RequestParam(required = false) String inviteCode,
                                               @RequestParam String source) {
        Integer client = source.equals("android") ? _Whole.ONE : source.equals("ios") ? _Whole.TWO : _Whole.ZERO;
        if (client <= _Whole.ZERO)
            throw new DataHandleException("客户端异常，请检查参数");
        //@create by FanJq 2024/12/25 17:18 校验验证码
        AliSmsUtils.check(mobile, CommonConstant.SMS_EVENT_REGISTER, captcha);

        //@create by FanJq 2024/12/25 17:05 获取用户信息
        User user = userService.queryByMobileAndNotDelFlag(mobile);
        //@create by FanJq 2024/7/8 15:23 校验是否注册
        if (ObjectUtil.isNotNull(user))
            throw new DataHandleException("手机号已注册，请前往登录");
        user = userService.appRegister(mobile, cipher, inviteCode);

        return success(createUserTokenMap(tokenBuild(user, client, ""), user));
    }

    /**
     * @Description
     * 组装登录返回数据
     * @date 2024/12/11 17:35
     * @author FanJq
     * @param token
     * @param user
     * @return {@link UserDetails}
    */
    public UserDetails createUserTokenMap(String token, User user) {
        //返参
        UserInfo userVO = userService.getUserInfo(user);
        UserDetails userDetails = new UserDetails();
        userDetails.setToken(token);
        userDetails.setUserInfo(userVO);
        return userDetails;
    }

    /**
     * @Description
     * 解密encryptedData,获取用户信息
     * @date 2024/12/11 18:02
     * @author FanJq
     * @param dto
     * @return {@link JSONObject}
    */
    public JSONObject getWxJsCode(WXLoginDto dto){
        //@create by FanJq 2024/7/8 15:27 根据小程序传过来的code想这个url发送请求
        Map wxApp = configService.queryNameAndValueByGroup("wxMiniApp");
        String url = String.format(_Whole.wxJsCodeUrl, wxApp.get("appId"), wxApp.get("appSecret"), dto.getCode());
        //@create by FanJq 2024/7/8 15:27 发送请求，返回Json字符串
        String str = AuthUtil.httpRequest(url, "GET", null);
        //@create by FanJq 2024/7/8 15:27 转成Json对象 获取openId
        JSONObject response = JSON.parseObject(str);
        String sessionKey = response.getString("session_key");// 密钥
        //@create by FanJq 2024/7/8 15:27 解密encryptedData,获取用户信息
        JSONObject wxResult = VansTool.decryptionUserInfo(dto.getEncryptedData(), sessionKey, dto.getIv());
        response.putAll(wxResult);
        return response;
    }

    /**
     * @Description
     * 获取App授权登录信息
     * @date 2024/12/25 17:04
     * @author FanJq
     * @param code
     * @return {@link JSONObject}
    */
    public JSONObject getWxAppCode(String code){
        //@create by FanJq 2024/7/8 15:27 根据小程序传过来的code想这个url发送请求
        Map wxApp = configService.queryNameAndValueByGroup("wxApp");
        String url = String.format(_Whole.wxAppCodeUrl, wxApp.get("appId"), wxApp.get("appSecret"), code);
        //@create by FanJq 2024/7/8 15:27 发送请求，返回Json字符串
        String str = AuthUtil.httpRequest(url, "GET", null);
        //@create by FanJq 2024/7/8 15:27 转成Json对象 获取openId
        JSONObject response = JSON.parseObject(str);
        return response;
    }
}
